package com.lmind.core.gps.terminal;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.LinkedBlockingQueue;

import org.apache.mina.core.service.IoAcceptor;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.lmind.bean.EventProvider;
import com.lmind.core.gps.terminal.message.AccessMessage;
import com.lmind.core.gps.terminal.message.AbstractMessage;
import com.lmind.core.gps.terminal.protocol.MinaProtocolFactory;

/**
 * 基于nio mina 实现的终端网关
 * @author 刘勉
 *
 */
public class DefaultTerminalGateway extends IoHandlerAdapter implements TerminalGateway {

	private static final Logger logger = LoggerFactory.getLogger(DefaultTerminalGateway.class);
	
	private EventProvider<TerminalGatewayListener> event = new EventProvider<TerminalGatewayListener>();
	
	private IoAcceptor acceptor;
	
	private int port = 15443;
	
	public int getPort() {
		return port;
	}

	public void start() throws IOException {
		
		acceptor = new NioSocketAcceptor(); 

        acceptor.getFilterChain().addLast( 
            "codec", 
            new ProtocolCodecFilter(new MinaProtocolFactory())); 

        acceptor.setHandler(this); 
        acceptor.bind(new InetSocketAddress(port));

        logger.info("计算器服务已启动，端口是" + 15443); 
	}
	
	public void stop() {
		acceptor.dispose(true);
	}
	
	@Override
	public void sessionCreated(IoSession session) throws Exception {
		super.sessionCreated(session);
	}

	@Override
	public void sessionOpened(IoSession session) throws Exception {
		
		logger.debug("sessionOpened:" + session.getId());
		
		for (TerminalGatewayListener listener : event.toList()) {
			listener.terminalConnected(session.getId());
		}
	}

	@Override
	public void sessionClosed(IoSession session) throws Exception {
		for (TerminalGatewayListener listener : event.toList()) {
			listener.terminalDisconnected(session.getId());
		}
	}

	@Override
	public void sessionIdle(IoSession session, IdleStatus status)
			throws Exception {
		
		super.sessionIdle(session, status);
	}

	@Override
	public void exceptionCaught(IoSession session, Throwable cause)
			throws Exception {
		// TODO Auto-generated method stub
		super.exceptionCaught(session, cause);
	}

	@Override
	public void messageReceived(IoSession session, Object message)
			throws Exception {
		
		logger.debug("messageReceived:" + message.toString());
		
		for (TerminalGatewayListener listener : event.toList()) {
			listener.terminalMessage(session.getId(), message);
		}
	}

	@Override
	public void messageSent(IoSession session, Object message) throws Exception {
		// TODO Auto-generated method stub
		super.messageSent(session, message);
	}

	@Override
	public void addTerminalGatewayListener(TerminalGatewayListener listener) {
		event.addEventListener(listener);
	}

	@Override
	public void removeTerminalGatewayListener(TerminalGatewayListener listener) {
		event.removeEventListener(listener);
	}

	@Override
	public void sendMessage(long sessionId, Object message) {
		IoSession session = acceptor.getManagedSessions().get(sessionId);
		if (session == null) {
			throw new GatewayException("该会话不存在或已断开");
		}
		
		send(session, message);
	}
	
	@Override
	public Object getAttribute(long sessionId, Object key) {
		IoSession session = getSession(sessionId);
		return session.getAttribute(key);
	}
	
	@Override
	public void setAttribute(long sessionId, Object key, Object value) {
		IoSession session = getSession(sessionId);
		session.setAttribute(key, value);
	}
	
	
	protected void send(IoSession session, Object message) {
		session.write(message);
	}
	
	private IoSession getSession(long sessionId) {
		IoSession session = acceptor.getManagedSessions().get(sessionId);
		if (session == null) {
			throw new GatewayException("该会话不存在或已断开");
		}
		return session;
	}	
	
	class Session {
		
		/**
		 * 发送信息队列
		 */
		private Queue<Object> sendQueue = new LinkedBlockingQueue<Object>();
		
	}

}
